#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include "../comm/util.hpp"
#include "../comm/Log.hpp"

namespace ns_compile
{
    using namespace ns_util;
    // 负责编译提交的代码
    class Compiler
    {
    public:
        static bool Compile(const std::string &filename)
        {
            // 要编译的文件放在了temp目录下
            // filename.exe filename.cc filename.err
            umask(0);
            int err_fd = open(PathUtil::CompileError(filename).c_str(), O_CREAT | O_WRONLY, 0644);
            if (err_fd < 0)
            {
                LOG(ERROR, "open error file fail");
                exit(1);
            }
            pid_t id = fork();
            if (id == 0)
            {
                // child
                // 1. 打开错误文件，没有就创建
                dup2(err_fd, 2);
                // 程序替换，编译代码 g++ -o target.ext src.cc -std=c++11
                execlp("g++", "g++", "-o", PathUtil::Exe(filename).c_str(), PathUtil::Src(filename).c_str(), "-std=c++11", "-D", "COMPILE_RUN", nullptr);
                // 失败才会走到这一步
                LOG(ERROR, "compile execlp fail");
                exit(2);
            }
            else if (id < 0)
            {
                // error
                close(err_fd);
                LOG(ERROR, "compile fork fail");
                return false;
            }
            // parent
            waitpid(id, nullptr, 0);
            close(err_fd);
            // 判断exe文件是否存在 是否编译成功
            if (FileUtil::FileIsExists(PathUtil::Exe(filename)))
            {
                LOG(INFO, "file: " + filename + " 编译成功");
                return true;
            }
            LOG(ERROR, "file: " + filename + " 编译失败");
            return false;
        }

    private:
    };
}
